//    Copyright (C) Kherty.  All rights reserved.
using System;

namespace OpenLS.Spreadsheet.StandardAddIn.Statistics
{
    internal sealed class GammaDistribution : ContinuousDistribution
    {

        public GammaDistribution(double alpha, double beta)
        {
            if (!IsValidParameters(alpha, beta))
                throw new ArgumentOutOfRangeException("alpha or beta");
            Alpha = alpha;
            Beta = beta;
        }

        public double Alpha{
            get;
            private set;}
       
        public double Beta{
            get;
            private set;}

        public double Probability(double x)
        {
            if (x == 0.0)
                return 0.0;
            return
                Math.Exp(Math.Log(Math.Pow(x, Alpha - 1)) + Math.Log(Math.Pow(1/Beta, Alpha)) - (1/Beta)*x -
                         Statistician.LogGamma(Alpha));
        }

        public override double CumulativeProbability(double x)
        {
            if (x <= 0.0)
                return 0.0;
            return Statistician.RegularizedGammaP(Alpha, x/Beta);
        }

        public override double InverseCumulativeProbability(double probability)
        {
            if (probability == 0)
                return 0;
            if (probability == 1)
                return double.PositiveInfinity;
            return base.InverseCumulativeProbability(probability);
        }

        protected override SolverParameters GetSolverParameters(double probability)
        {
            return new SolverParameters(double.MinValue,
                                        probability < 0.5 ? Alpha*Beta : double.MaxValue,
                                        probability < 0.5 ? Alpha*Beta/2 : Alpha*Beta);
        }

        internal static bool IsValidParameters(double alpha, double beta)
        {
            return alpha > 0 || beta > 0;
        }
    }
}